# Copyright (C) 2007 by Sergio Pistone
# sergio_pistone@yahoo.com.ar
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the
# Free Software Foundation, Inc.,
# 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.

if $0 == __FILE__
	puts "Nothing to see here..."
	puts "Did you meant to run plugins_tests.rb?"
	exit 1
end

require File.expand_path( File.dirname( __FILE__ ) + "/../utils/htmlentities" )
require "test/unit"

class PluginTests < Test::Unit::TestCase

	def self.build_suite( plugin, cases )
		@@tmp_plugin = plugin
		@@tmp_cases = cases
		eval(
			"class #{plugin.class.name}Tests < PluginTests\n" + \
				"@@plugin = @@tmp_plugin\n" + \
				"@@cases = @@tmp_cases\n" + \
				"def self.plugin()\n" + \
					"return @@plugin\n" + \
				"end\n" + \
				"def self.cases()\n" + \
					"return @@cases\n" + \
				"end\n" + \
			"end"
		)
		return eval( "#{plugin.class.name}Tests.suite()" )
	end

	def plugin()
		return self.class.plugin()
	end

	def cases()
		return self.class.cases()
	end

	def lyrics_test_data()
		test_data = plugin().lyrics_test_data()
		return test_data if ! cases() || cases().empty?
		test_data2 = []
		cases().each() { |index| test_data2 << test_data[index] if test_data[index] }
		return test_data2
	end

	def suggestions_test_data()
		test_data = plugin().suggestions_test_data()
		return test_data if ! cases() || cases().empty?
		test_data2 = []
		cases().each() { |index| test_data2 << test_data[index] if test_data[index] }
		return test_data2
	end

	def check_suggestions( suggestions, request, site_name )
		assert_not_nil( suggestions, "No suggestions for #{request.title} by #{request.artist} returned by #{site_name}" )
		assert( ! suggestions.empty?, "Empty suggestions list for #{request.title} by #{request.artist} returned by #{site_name}" )
		suggestions.each() do |suggestion|
			sugg = { "artist" => suggestion.artist, "title" => suggestion.title }
			sugg.each() do |key, value|
				assert_nil(
					value.downcase().index( "lyrics" ),
					"Suggestions for #{request.title} by #{request.artist} returned by #{site_name} contains the 'lyrics' word (#{value})"
				)
				assert(
					value == HTMLEntities.decode( value ),
					"Suggestions for #{request.title} by #{request.artist} returned by #{site_name} contains unexpected HTML entities (#{value})"
				)
			end
		end
	end

	def check_response( response, request, site_name )
		[response.artist.to_s(), response.title.to_s(), response.album.to_s()].each() do |metadata|
			assert_nil(
				metadata.downcase().index( "lyrics" ),
				"Lyrics metadata for #{request.title} by #{request.artist} returned by #{site_name} contains the 'lyrics' word"
			)
		end
		assert_not_nil(
			response.lyrics,
			"No lyrics for #{request.title} by #{request.artist} returned by #{site_name}"
		)
		assert(
			! response.lyrics.strip().empty?,
			"Empty lyrics for #{request.title} by #{request.artist} returned by #{site_name}"
		)
		# assert(
		# 	response.lyrics.include?( "\n" ),
		# 	"Lyrics for #{request.title} by #{request.artist} returned by #{site_name} don't have any line breaks"
		# )
		md = /<\/?(a|h[1-6]|hr|p|br|body|html|span|div|br|script|!?--) *\/?>*/i.match( response.lyrics )
		assert_nil(
			md,
			"Lyrics for #{request.title} by #{request.artist} returned" + \
			" by #{site_name} contains unexpected HTML tags: #{md ? md[1] : ""}"
		)
	end

	def test_lyrics_direct_search()
		puts "\nTesting #{plugin().site_name()} lyrics direct search..."
		lyrics_test_data().each() do |request|
			fetch_data = plugin().build_lyrics_fetch_data( request )
			if fetch_data.url
				puts " - searching lyrics for #{request.title} by #{request.artist}"
				response = plugin().lyrics_direct_search( request )
				check_response( response, request, plugin.site_name() )
			else
				puts " - skipping lyrics search for #{request.title} by #{request.artist} (no direct fetch data received)"
				break
			end
		end
	end

	def test_lyrics_from_suggestions()
		puts "\nTesting #{plugin().site_name()} lyrics from suggestions..."
		suggestions_test_data().each() do |request|
			puts " - searching suggestions for #{request.title} by #{request.artist}"
			suggestions = plugin().suggestions( request )
			check_suggestions( suggestions, request, plugin.site_name() )
			puts " - searching lyrics to #{request.title} by #{request.artist} in suggestions"
			response, suggestions = plugin().lyrics_from_suggestions( request, suggestions )
			check_response( response, request, plugin.site_name() )
		end
	end

	def test_lyrics_full_search()
		puts "\nTesting #{plugin().site_name()} lyrics full search..."
		lyrics_test_data().each() do |request|
			puts " - searching lyrics for #{request.title} by #{request.artist}"
			response = plugin().lyrics_full_search( request )
			check_response( response, request, plugin.site_name() )
		end
	end

	def test_no_lyrics_found()
		puts "\nTesting #{plugin().site_name()} forced retrieval fail..."
		request = Lyrics::Request.new( "Fake Artist", "Fake Title", "Fake Album" )
		puts " - searching lyrics for #{request.title} by #{request.artist}"
		response = plugin().lyrics_full_search( request )
		assert_nil( response.lyrics, "Unexpected lyrics returned for #{request.title} by #{request.artist} by #{plugin.site_name()}" )
	end

end
